package com.fingard.dsp.bank.directbank.gac01;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptData;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptDataHelper;
import com.fingard.dsp.bank.directConfig.BankConfig;
import com.fingard.dsp.bank.directConfig.ReceiptProConfig;
import com.fingard.dsp.bank.directbank.bankInterface.IReceiptPro;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.ReqQryReceipt;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.RetAtsReceipt;
import com.fingard.dsp.bank.reqrespobj.enumeration.ENReceiptState;
import com.fingard.dsp.bank.reqrespobj.transaction.Req7516HisTrans;
import com.fingard.io.FileHelper;
import com.fingard.text.StringHelper;
import com.fingard.util.DateHelper;
import com.fingard.util.ZipHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

import java.io.File;
import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * @author Parker on 2020-06-19.
 * @version 1.0
 */
public class GAC01ReceiptPro extends GAC01Base implements IReceiptPro {
    @Override
    public RetAtsReceipt qryReceiptOneDay(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay) throws Exception {
        //先查历史明细
        GAC01Transaction transaction = new GAC01Transaction();
        transaction.reqHeader = pReqReceipt.reqHeader;
        transaction.bankFront = this.bankFront;
        transaction.sbLog = this.sbLog;
        pReqReceipt.reqHeader.transType = "7516";
        Req7516HisTrans tmpReq7516 = new Req7516HisTrans(pReqReceipt.reqHeader);
        tmpReq7516.actArea = pReqReceipt.areaCode;
        tmpReq7516.actCur = pReqReceipt.actCur;
        tmpReq7516.actNum = pReqReceipt.actNum;
        tmpReq7516.dateFrom = Format.Date8Format.format(pOneDay);
        tmpReq7516.dateTo = Format.Date8Format.format(pOneDay);
        tmpReq7516.directRight = pReqReceipt.directRight;

        //指明是回单查询发起的历史明细查询
        transaction.isFromReceiptQry = true;
        //调用历史明细查询 接口查询CCBS交易流水号
        transaction.d_7516_HisTrans(tmpReq7516);
        pReqReceipt.reqHeader.transType = "DOWNLOADRECEIPT";

        List<String> receiptCodes = transaction.receiptCodes;
        qryReceiptDataAndFile(receiptCodes, pConfig, pReqReceipt, pOneDay);
        //回单文件本地文件
        String localpath = pConfig.getSaveSubDir(pReqReceipt.reqHeader, pOneDay) + File.separator + Format.Date8Format.format(pOneDay);
        getPdfFiles(pConfig, pReqReceipt, pOneDay, localpath, receiptCodes);
        return null;
    }

    /**
     * 公共方法，下载的日期目录中提取pdf文件
     */
    protected void getPdfFiles(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay, String pReceiptDir, List<String> dataList) {
        ReceiptDataHelper receiptHelper = null;//回单数据保存类，分区分表
        try {
            receiptHelper = new ReceiptDataHelper(pReqReceipt.reqHeader.tenant, pOneDay);
            File receiptDir = new File(pReceiptDir);

            int[] retVals = getPdfLoop(pConfig, pReqReceipt, pOneDay, receiptHelper, receiptDir, dataList);
            //[0]总数 [1]新增 [2]已存在
            WriteBankLogLn("目录" + pReceiptDir + "\r\n遍历总数" + retVals[0] + "，新增" + retVals[1] + "条，已存在" + (retVals[0] - retVals[1]) + "条");
        } catch (Exception ex) {
            this.WriteBankLogLn(ex);
        } finally {
            if (receiptHelper != null) {
                receiptHelper.close();
            }
        }
    }

    /**
     * 公共方法，提取pdf文件，农行是所有账号的回单一起提供，遍历所有pdf
     * [0]总数 [1]新增 [2]已存在
     */
    protected int[] getPdfLoop(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay, ReceiptDataHelper pReceiptHelper, File pDir, List<String> dataList) {
        String qryDay8 = Format.Date8Format.format(pOneDay);
        int[] retVals = new int[2];
        retVals[0] = 0;//总pdf个数
        retVals[1] = 0;//新增
        File[] files = pDir.listFiles();
        for (File eachFile : files) {
            try {
                if (eachFile.isDirectory()) {
                    int[] subVals = getPdfLoop(pConfig, pReqReceipt, pOneDay, pReceiptHelper, eachFile, dataList);
                    retVals[0] = retVals[0] + subVals[0];
                    retVals[1] = retVals[1] + subVals[1];
                }
                String[] nameAndExt = StringHelper.splitFileNameAndExt(eachFile.getName());
                if ("pdf".equalsIgnoreCase(nameAndExt[1])) {
                    retVals[0] = retVals[0] + 1;
                    //回单编号
                    String[] nameSp = nameAndExt[0].split("_");
                    if (nameSp.length != 1) {
                        WriteBankLogLn("回单文件:" + eachFile.getName() + "文件名格式不符合预期");
                        continue;
                    }

                    for (String istNbr : dataList) {
                        if (nameSp[0].contains(istNbr)) {
                            //重命名
                            String renameToPath = pConfig.getSaveSubDir(pReqReceipt.reqHeader, pOneDay) + File.separator + qryDay8 + File.separator + pReqReceipt.actNum;
                            FileHelper.mkdirsIfNotExists(renameToPath);
                            renameToPath += File.separator + eachFile.getName();
                            File destFile = new File(renameToPath);
                            boolean reResult;
                            if (destFile.exists()) {
                                reResult = true;
                            } else {
                                reResult = eachFile.renameTo(destFile);
                            }
                            if (reResult) {
                                //数据库中存储的路径是相对pConfig.localSaveMainDir的相对路径
                                String relativePath = StringHelper.getRelativePath(destFile.getAbsolutePath(), pConfig.localSaveMainDir);
                                int inRe = pReceiptHelper.updateDownState(pReqReceipt.actNum, istNbr, relativePath, eachFile.getName(), ENReceiptState.SUCCESS.getValue());
                                if (inRe > 0) {
                                    retVals[1] = retVals[1] + 1;
                                }
                                WriteBankLogLn("回单编号" + istNbr + "，文件" + eachFile.getName() + "下载成功，重命名成功，更新影响行数：" + inRe);
                            } else {
                                WriteBankLogLn("回单编号" + istNbr + "重命名失败：\r\n" + eachFile.getAbsolutePath() + "\r\n重命名为：\r\n" + renameToPath);
                            }
                            break;
                        }
                    }
                }
            } catch (Exception ex) {
                WriteBankLogLn(ex, eachFile.getAbsolutePath());
            }
        }
        return retVals;
    }

    private void qryReceiptDataAndFile(List<String> receiptCodes, ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay) throws Exception {
        String qryDay8 = Format.Date8Format.format(pOneDay);
        ReceiptDataHelper receiptHelper = new ReceiptDataHelper(pReqReceipt.reqHeader.tenant, pOneDay);//回单数据保存类，分区分表
        //回单文件本地文件
        String localpath = pConfig.getSaveSubDir(pReqReceipt.reqHeader, pOneDay) + File.separator + qryDay8;
        FileHelper.mkdirsIfNotExists(localpath);

        for (String receiptCode : receiptCodes) {
            try {
                XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
                writeCommonHeader(xmlWriter);
                xmlWriter.writeStartElement("Iss_Itreasury");
                xmlWriter.writeStartElement("QueryReq");
                xmlWriter.writeElementString("OperationType", "21");//操作类型
                xmlWriter.writeElementString("SystemID", bankFront.termid);//系统ID
                for (int i = 1; i < 9; i++) {
                    xmlWriter.writeStartElement("QueryContent");
                    xmlWriter.writeElementString("ClientCode", bankFront.org);
                    xmlWriter.writeElementString("TransNO", receiptCode);
                    xmlWriter.writeElementString("BillType", String.valueOf(i));
                    xmlWriter.writeEndElement();
                }
                xmlWriter.writeEndDocument();

                String[] tmpRetBkStr = sendToBank(xmlWriter.toXmlString(), pReqReceipt.reqHeader.transType, pReqReceipt.reqHeader.transType);
                if (tmpRetBkStr[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpRetBkStr[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        while (tmpBkReader.read("/Iss_Itreasury/QueryRen/RenContent")) {
                            ReceiptData rcpt = new ReceiptData();
                            rcpt.ownAct = pReqReceipt.actNum;
                            rcpt.bank = "907";
                            rcpt.srcSys = "GAC01";
                            rcpt.istNbr = receiptCode;//SERIAL_NO 流水号
                            rcpt.receiptNo = receiptCode;//SERIAL_NO 流水号
                            /**银行流水号*/
                            rcpt.bnkSeqNo = receiptCode;
                            /**业务参考号*/
                            rcpt.busRef = receiptCode;
                            rcpt.busDate = Integer.parseInt(qryDay8);
                            String TRAN_DATE = DateHelper.convertD10toD8(tmpBkReader.readedXElement.getSingleTextNotNull("ExecuteDate"));
                            if (!qryDay8.equals(TRAN_DATE)) {
                                WriteBankLogLn(rcpt.receiptNo + "回单数据的日期" + TRAN_DATE + "与预期" + qryDay8 + "不符");
                                continue;
                            }
                            String ownAct = tmpBkReader.readedXElement.getSingleTextNotNull("PayerAcctCode");
                            if (pReqReceipt.actNum.equals(ownAct)) {
                                rcpt.moneyWay = "1";
                                rcpt.oppActNum = tmpBkReader.readedXElement.getSingleTextNotNull("PayeeAcctNo");
                                rcpt.oppActName = tmpBkReader.readedXElement.getSingleTextNotNull("PayeeAcctName");
                            } else {
                                rcpt.moneyWay = "2";
                                rcpt.oppActNum = tmpBkReader.readedXElement.getSingleTextNotNull("PayerAcctCode");
                                rcpt.oppActName = tmpBkReader.readedXElement.getSingleTextNotNull("PayerAcctName");
                            }
                            rcpt.amount = new BigDecimal(tmpBkReader.readedXElement.getSingleTextNotNull("LowerAmount"));
                            rcpt.voucherNo = receiptCode;
                            rcpt.cur = convertCurToATS(pReqReceipt.actCur);
                            int inRe = receiptHelper.insertIfNotExist(rcpt, true);
                            WriteBankLogLn(rcpt.receiptNo + "写入数据库，影响行数：" + inRe);
                        }
                    } else {
                        WriteBankLogLn("查询" + Format.Date8Format.format(pOneDay) + "日,回单编号：" + receiptCodes + "的回单数据失败, 原因:" + tmpSbMsg);
                    }
                }
                WriteBankLogLn(pReqReceipt.actNum + "，" + Format.Date8Format.format(pOneDay) + "回单数据查询完成.");

                xmlWriter = new XmlTextWriter();//发银行报文的XML对象
                writeCommonHeader(xmlWriter);
                xmlWriter.writeStartElement("Iss_Itreasury");
                xmlWriter.writeStartElement("QueryReq");
                xmlWriter.writeElementString("OperationType", "22");//操作类型
                xmlWriter.writeElementString("SystemID", getQryTransID());//系统ID
                for (int i = 1; i < 9; i++) {
                    xmlWriter.writeStartElement("QueryContent");
                    xmlWriter.writeElementString("ClientCode", bankFront.org);
                    xmlWriter.writeElementString("TransNO", receiptCode);
                    xmlWriter.writeElementString("BillType", String.valueOf(i));
                    xmlWriter.writeEndElement();
                }
                xmlWriter.writeEndDocument();
                tmpRetBkStr = sendToBank(xmlWriter.toXmlString(), pReqReceipt.reqHeader.transType, pReqReceipt.reqHeader.transType);
                if (tmpRetBkStr[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpRetBkStr[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        while (tmpBkReader.read("/Iss_Itreasury/QueryRen/RenContent")) {
                            String pdfStream = tmpBkReader.readedXElement.getSingleTextNotNull("data/pdfStream");
                            String zipFile = localpath + File.separator + receiptCode + ".zip";
                            FileOutputStream outputStream = null;
                            try {
                                outputStream = new FileOutputStream(new File(zipFile));
                                sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
                                outputStream.write(decoder.decodeBuffer(pdfStream));
                            } catch (Exception ex) {
                                ex.printStackTrace();
                                WriteBankLogLn("生成" + Format.Date8Format.format(pOneDay) + "日回单文件失败, 原因:" + ex.getMessage());
                            } finally {
                                if (outputStream != null) {
                                    outputStream.close();
                                }
                            }
                            if (FileHelper.existFile(zipFile)) {
                                WriteBankLogLn("开始解压文件:" + zipFile);
                                ZipHelper.unzipFile(zipFile, localpath);
                                WriteBankLogLn("文件解压已完成.");
                                File depressDir = new File(localpath);
                                File[] deFiles = depressDir.listFiles();
                                if (deFiles == null || deFiles.length <= 0) {
                                    WriteBankLogLn("解压后文件夹" + localpath + "下为空");
                                }
                            }
                        }
                    } else {
                        WriteBankLogLn("下载" + Format.Date8Format.format(pOneDay) + "日回单文件失败, 原因:" + tmpSbMsg);
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
                WriteBankLogLn("生成" + Format.Date8Format.format(pOneDay) + "日回单数据或文件失败, 原因:" + ex.getMessage());
            }
        }
    }

}
